package com.twinkle.rpc.client.proxy;

import com.twinkle.rpc.client.communication.RpcClient;
import com.twinkle.rpc.client.communication.impl.NettyRpcClient;
import com.twinkle.rpc.common.message.RpcRequest;
import com.twinkle.rpc.common.message.RpcResponse;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author twinkle
 * @version 1.0
 * 代理对象类：客户端获取代理对象实例，调用对应的方法，
 * 每一次调用都会对方法进行增强，将调用方法的接口名、
 * 方法名、参数类型、参数封装成一个request发送给服务端，
 * 并调用通信模块的方法发送给服务端并接受来自服务端的响应结果
 * 返回 response.data
 */
public class ClientProxy implements InvocationHandler {
    //传入参数service接口的class对象，反射封装成一个request
    private RpcClient rpcClient;
    public ClientProxy(){
         rpcClient = new NettyRpcClient();
    }

    //jdk动态代理，每一次代理对象调用方法，都会经过此方法增强（反射获取request对象，socket发送到服务端）
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //构建request
        RpcRequest request= RpcRequest.builder()
                .interfaceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .params(args).paramsType(method.getParameterTypes()).build();
        //和服务端进行数据传输
        RpcResponse response= rpcClient.sendRequest(request);
        return response.getData();
    }
    public <T>T getProxy(Class<T> clazz){
        Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
        return (T)o;
    }
}
